Model Selection

In this section, we will compare the performance of three different models: Linear, Exponential, and Log-Transformed for each fungal species at various temperatures. We will compare the following metrics:

  • Residual Sum of Squares (RSS): Lower values indicate a better fit.
  • Adjusted R-squared: Higher values indicate a better fit.
  • AIC (Akaike Information Criterion): Lower values indicate a better model fit considering model complexity.
  • BIC (Bayesian Information Criterion): Lower values indicate a better model fit, penalizing model complexity more heavily than AIC.
df <- read.csv("Rosalynn Tidy data.csv")
#Filter week 1-5, Suillus data up to week 6. 
df_1_5 <- df %>%
  filter(Week %in% 1:5)
# Convert relevant columns to factors
df_1_5$Temperature..Celsius. <- as.factor(df_1_5$Temperature..Celsius.)
#df_1_5$Week <- as.factor(df_1_5$Week)
df_1_5$Species <- as.factor(df_1_5$Species)
# Rename the column
colnames(df_1_5)[colnames(df_1_5) == "Temperature..Celsius."] <- "Temperature"

# Initialize an empty list to store model metrics
model_metrics <- list()

# Loop over each species and temperature to fit models and calculate metrics
for(species in unique(df_1_5$Species)) {
  for(temp in unique(df_1_5$Temperature)) {
    
    # Filter the data for this species and temperature
    df_subset <- df_1_5 %>% filter(Species == species, Temperature == temp)
    
    # Fit the Linear Model
    linear_model <- lm(Growth ~ Week, data = df_subset)
    
    # Fit the Exponential Model (log-transformed linear)
    exp_model <- lm(log(Growth) ~ Week, data = df_subset)
    
    # Fit the Logarithmic Model (Growth ~ log(Week))
    log_fit_model <- lm(Growth ~ log(Week), data = df_subset)
    
    # Calculate Metrics for each model
    metrics <- data.frame(
      Species = species,
      Temperature = temp,
      Metric = c("RSS", "Adjusted R-squared", "AIC", "BIC"),
      Linear_Model = c(sum(residuals(linear_model)^2),
                       summary(linear_model)$adj.r.squared,
                       AIC(linear_model),
                       BIC(linear_model)),
      Exponential_Model = c(sum(residuals(exp_model)^2),
                            summary(exp_model)$adj.r.squared,
                            AIC(exp_model),
                            BIC(exp_model)),
      Logarithmic_Model = c(sum(residuals(log_fit_model)^2),
                            summary(log_fit_model)$adj.r.squared,
                            AIC(log_fit_model),
                            BIC(log_fit_model))
    )
    
    # Determine the best model for each metric
    metrics$Best_Model <- sapply(1:nrow(metrics), function(i) {
      if (metrics$Metric[i] == "Adjusted R-squared") {
        # For Adjusted R-squared, higher is better
        if (metrics$Linear_Model[i] == max(metrics$Linear_Model[i], metrics$Exponential_Model[i], metrics$Logarithmic_Model[i])) {
          "Linear Model"
        } else if (metrics$Exponential_Model[i] == max(metrics$Linear_Model[i], metrics$Exponential_Model[i], metrics$Logarithmic_Model[i])) {
          "Exponential Model"
        } else {
          "Logarithmic Model"
        }
      } else {
        # For RSS, AIC, and BIC, lower is better
        if (metrics$Linear_Model[i] == min(metrics$Linear_Model[i], metrics$Exponential_Model[i], metrics$Logarithmic_Model[i])) {
          "Linear Model"
        } else if (metrics$Exponential_Model[i] == min(metrics$Linear_Model[i], metrics$Exponential_Model[i], metrics$Logarithmic_Model[i])) {
          "Exponential Model"
        } else {
          "Logarithmic Model"
        }
      }
    })
    
    # Store the metrics in the list
    model_metrics[[paste(species, temp, sep = "_")]] <- metrics
  }
}

# Combine all metrics into one data frame
model_comparison <- do.call(rbind, model_metrics)
# Display the table of model comparison with scrolling enabled for rows
model_comparison %>%
  kbl(caption = "Model Comparison for Different Species and Temperatures") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = TRUE, 
                fixed_thead = TRUE) %>%
  scroll_box(height = "400px")
Model Comparison for Different Species and Temperatures
Species Temperature Metric Linear_Model Exponential_Model Logarithmic_Model Best_Model
Suillus lakei_15.1 Suillus lakei 15 RSS 272.5171720 48.4593445 308.8850664 Exponential Model
Suillus lakei_15.2 Suillus lakei 15 Adjusted R-squared 0.4613154 0.4191081 0.3894270 Linear Model
Suillus lakei_15.3 Suillus lakei 15 AIC 378.5981283 212.8083901 390.6238204 Exponential Model
Suillus lakei_15.4 Suillus lakei 15 BIC 386.2911729 220.5014347 398.3168650 Exponential Model
Suillus lakei_20.1 Suillus lakei 20 RSS 1002.9973785 83.2938163 1119.0928300 Exponential Model
Suillus lakei_20.2 Suillus lakei 20 Adjusted R-squared 0.4608752 0.4044651 0.3984724 Linear Model
Suillus lakei_20.3 Suillus lakei 20 AIC 503.6905967 264.8067059 514.2050436 Exponential Model
Suillus lakei_20.4 Suillus lakei 20 BIC 511.3836413 272.4997505 521.8980882 Exponential Model
Suillus lakei_25.1 Suillus lakei 25 RSS 781.7938038 65.6273240 805.7073113 Exponential Model
Suillus lakei_25.2 Suillus lakei 25 Adjusted R-squared 0.4289472 0.4447257 0.4114798 Exponential Model
Suillus lakei_25.3 Suillus lakei 25 AIC 479.7715107 241.9220169 482.6639438 Exponential Model
Suillus lakei_25.4 Suillus lakei 25 BIC 487.4645552 249.6150614 490.3569883 Exponential Model
Rhizopogon Evadens_15.1 Rhizopogon Evadens 15 RSS 86.1196845 13.2576726 103.3863906 Exponential Model
Rhizopogon Evadens_15.2 Rhizopogon Evadens 15 Adjusted R-squared 0.5835773 0.6896881 0.5000860 Exponential Model
Rhizopogon Evadens_15.3 Rhizopogon Evadens 15 AIC 223.2203249 88.4966925 236.3772683 Exponential Model
Rhizopogon Evadens_15.4 Rhizopogon Evadens 15 BIC 230.0503232 95.3266909 243.2072666 Exponential Model
Rhizopogon Evadens_20.1 Rhizopogon Evadens 20 RSS 81.1488243 10.9114338 93.0074793 Exponential Model
Rhizopogon Evadens_20.2 Rhizopogon Evadens 20 Adjusted R-squared 0.7593021 0.7736558 0.7241278 Exponential Model
Rhizopogon Evadens_20.3 Rhizopogon Evadens 20 AIC 218.9396942 74.4735953 228.7601419 Exponential Model
Rhizopogon Evadens_20.4 Rhizopogon Evadens 20 BIC 225.7696926 81.3035936 235.5901403 Exponential Model
Rhizopogon Evadens_25.1 Rhizopogon Evadens 25 RSS 51.1903435 6.3616754 58.1441995 Exponential Model
Rhizopogon Evadens_25.2 Rhizopogon Evadens 25 Adjusted R-squared 0.8685156 0.8745631 0.8506544 Exponential Model
Rhizopogon Evadens_25.3 Rhizopogon Evadens 25 AIC 185.7668538 35.6281960 194.9378691 Exponential Model
Rhizopogon Evadens_25.4 Rhizopogon Evadens 25 BIC 192.5968522 42.4581944 201.7678674 Exponential Model
Rhizopogon idahoensis_15.1 Rhizopogon idahoensis 15 RSS 18.0173406 1.9029686 44.3805142 Exponential Model
Rhizopogon idahoensis_15.2 Rhizopogon idahoensis 15 Adjusted R-squared 0.9365388 0.9605924 0.8436818 Exponential Model
Rhizopogon idahoensis_15.3 Rhizopogon idahoensis 15 AIC 110.5832836 -51.2669267 175.4888245 Exponential Model
Rhizopogon idahoensis_15.4 Rhizopogon idahoensis 15 BIC 117.4132820 -44.4369284 182.3188228 Exponential Model
Rhizopogon idahoensis_20.1 Rhizopogon idahoensis 20 RSS 141.0385235 8.7132622 147.8315730 Exponential Model
Rhizopogon idahoensis_20.2 Rhizopogon idahoensis 20 Adjusted R-squared 0.8269137 0.8564575 0.8185771 Exponential Model
Rhizopogon idahoensis_20.3 Rhizopogon idahoensis 20 AIC 258.7375692 58.2761187 262.1244878 Exponential Model
Rhizopogon idahoensis_20.4 Rhizopogon idahoensis 20 BIC 265.5675675 65.1061171 268.9544862 Exponential Model
Rhizopogon idahoensis_25.1 Rhizopogon idahoensis 25 RSS 146.0640837 6.1040871 220.0835233 Exponential Model
Rhizopogon idahoensis_25.2 Rhizopogon idahoensis 25 Adjusted R-squared 0.9028412 0.9082441 0.8536050 Exponential Model
Rhizopogon idahoensis_25.3 Rhizopogon idahoensis 25 AIC 261.2584610 32.6522046 290.7757012 Exponential Model
Rhizopogon idahoensis_25.4 Rhizopogon idahoensis 25 BIC 268.0884593 39.4822030 297.6056996 Exponential Model
Cenococcum geophilum_15.1 Cenococcum geophilum 15 RSS 7.1878215 0.7879639 11.8191430 Exponential Model
Cenococcum geophilum_15.2 Cenococcum geophilum 15 Adjusted R-squared 0.7445867 0.9157614 0.5800165 Exponential Model
Cenococcum geophilum_15.3 Cenococcum geophilum 15 AIC 45.1730730 -7.8835153 57.1090498 Exponential Model
Cenococcum geophilum_15.4 Cenococcum geophilum 15 BIC 48.7072345 -4.3493538 60.6432113 Exponential Model
Cenococcum geophilum_20.1 Cenococcum geophilum 20 RSS 27.5942390 0.2729779 60.0069928 Exponential Model
Cenococcum geophilum_20.2 Cenococcum geophilum 20 Adjusted R-squared 0.8584880 0.9863473 0.6922651 Exponential Model
Cenococcum geophilum_20.3 Cenococcum geophilum 20 AIC 77.4583261 -33.3249922 96.1028241 Exponential Model
Cenococcum geophilum_20.4 Cenococcum geophilum 20 BIC 80.9924876 -29.7908307 99.6369856 Exponential Model
Cenococcum geophilum_25.1 Cenococcum geophilum 25 RSS 26.8718899 0.7088069 66.0314738 Exponential Model
Cenococcum geophilum_25.2 Cenococcum geophilum 25 Adjusted R-squared 0.9126857 0.9711796 0.7854453 Exponential Model
Cenococcum geophilum_25.3 Cenococcum geophilum 25 AIC 76.8216958 -10.4243741 98.3989138 Exponential Model
Cenococcum geophilum_25.4 Cenococcum geophilum 25 BIC 80.3558573 -6.8902126 101.9330753 Exponential Model
Laccaria bicolor_15.1 Laccaria bicolor 15 RSS 10.1641654 2.2452263 31.1866296 Exponential Model
Laccaria bicolor_15.2 Laccaria bicolor 15 Adjusted R-squared 0.9828993 0.9055001 0.9475299 Linear Model
Laccaria bicolor_15.3 Laccaria bicolor 15 AIC 53.4885979 17.2471093 80.3955048 Exponential Model
Laccaria bicolor_15.4 Laccaria bicolor 15 BIC 57.0227594 20.7812708 83.9296663 Exponential Model
Laccaria bicolor_20.1 Laccaria bicolor 20 RSS 32.5923101 2.3459816 20.3178084 Exponential Model
Laccaria bicolor_20.2 Laccaria bicolor 20 Adjusted R-squared 0.9604422 0.8754175 0.9753399 Logarithmic Model
Laccaria bicolor_20.3 Laccaria bicolor 20 AIC 81.4535907 18.3006513 70.1117040 Exponential Model
Laccaria bicolor_20.4 Laccaria bicolor 20 BIC 84.9877521 21.8348128 73.6458655 Exponential Model
Laccaria bicolor_25.1 Laccaria bicolor 25 RSS 12.7693784 1.0852276 43.0128546 Exponential Model
Laccaria bicolor_25.2 Laccaria bicolor 25 Adjusted R-squared 0.9772213 0.9364364 0.9232715 Linear Model
Laccaria bicolor_25.3 Laccaria bicolor 25 AIC 58.9649575 -0.2012898 88.1117340 Exponential Model
Laccaria bicolor_25.4 Laccaria bicolor 25 BIC 62.4991190 3.3328717 91.6458955 Exponential Model

Model Building: Exponential Models

In this section, we build exponential models to describe the growth of fungi at different temperatures. We will visualize both the raw data and the predicted data from the exponential models, and offer the option to compare them in the same plot.

# Create a list to store the fitted models and predicted data
exponential_models <- list()
predicted_data_list <- list()

# Loop over each species and temperature to fit exponential models
for(species in unique(df_1_5$Species)) {
  for(temp in unique(df_1_5$Temperature)) {
    
    # Filter the data for this species and temperature
    df_subset <- df_1_5 %>% filter(Species == species, Temperature == temp)
    
    # Fit the Exponential Model (log-transformed linear)
    exp_model <- lm(log(Growth) ~ Week, data = df_subset)
    
    # Store the model
    model_name <- paste("Exp_Model", species, temp, sep = "_")
    exponential_models[[model_name]] <- exp_model
    
    # Generate predicted values
    predicted_log_growth <- predict(exp_model, newdata = df_subset)
    predicted_growth <- exp(predicted_log_growth)  # Back-transform to the original scale
    
    # Store predicted data in a data frame
    df_predicted <- df_subset %>%
      mutate(Predicted_Growth = predicted_growth)
    
    # Store the predicted data for later use
    predicted_data_list[[model_name]] <- df_predicted
  }
}

# Combine all predicted data into one data frame for easier use
all_predicted_data <- bind_rows(predicted_data_list)

# Print a sample of the predicted data
head(all_predicted_data)
##   Temperature       Species strain_ID Week Plate Growth Predicted_Growth
## 1          15 Suillus lakei   Suilla     1     1  0.499         0.721077
## 2          15 Suillus lakei   Suilla     1     2  0.712         0.721077
## 3          15 Suillus lakei   Suilla     1     3  0.724         0.721077
## 4          15 Suillus lakei   Suilla     1     4  0.673         0.721077
## 5          15 Suillus lakei   Suilla     1     5  0.717         0.721077
## 6          15 Suillus lakei   Suilla     1     6  0.577         0.721077

Compare Raw and Fitted Data

Exponential Model Summary for Each Species at Each Temperature

The table below summarizes the results of fitting exponential models for each fungal species at different temperatures. For each combination of species and temperature, the following details are provided:

  • F-Value: This is the F-statistic for the model, which assesses the overall significance of the model.
  • P-Value: The P-value indicates the significance of the model. A lower P-value (< 0.05) suggests that the model is statistically significant.
  • Degrees of Freedom: This represents the number of data points minus the number of parameters estimated by the model.
  • Model Equation: The fitted equation for the model, represented as a linear relationship between the logarithm of growth and time (weeks).
# Initialize a data frame to store the summary information
model_summary <- data.frame(Species = character(), 
                            Temperature = numeric(), 
                            F_Value = numeric(), 
                            P_Value = numeric(), 
                            Degrees_of_Freedom = character(), 
                            Equation = character(),
                            stringsAsFactors = FALSE)

# Loop over each species and temperature to fit exponential models and extract metrics
for(species in unique(df_1_5$Species)) {
  for(temp in unique(df_1_5$Temperature)) {
    
    # Filter the data for this species and temperature
    df_subset <- df_1_5 %>% filter(Species == species, Temperature == temp)
    
    # Fit the exponential model (log-transformed linear)
    exp_model <- lm(log(Growth) ~ Week, data = df_subset)
    
    # Extract model summary details
    model_summary_info <- summary(exp_model)
    
    # Extract F-value, P-value, and degrees of freedom
    f_value <- model_summary_info$fstatistic[1]
    p_value <- pf(f_value, model_summary_info$fstatistic[2], model_summary_info$fstatistic[3], lower.tail = FALSE)
    df1 <- model_summary_info$fstatistic[2]  # Numerator degrees of freedom
    df2 <- model_summary_info$fstatistic[3]  # Denominator degrees of freedom
    
    # Extract the model equation
    intercept <- coef(exp_model)[1]
    slope <- coef(exp_model)[2]
    equation <- paste0("log(Growth) = ", round(intercept, 4), " + ", round(slope, 4), " * Week")
    
    # Store the results in the data frame
    model_summary <- rbind(model_summary, data.frame(Species = species, 
                                                     Temperature = temp, 
                                                     F_Value = f_value, 
                                                     P_Value = p_value, 
                                                     Degrees_of_Freedom = paste(df1, df2, sep = ", "), 
                                                     Equation = equation))
  }
}

# Create a scrollable table
model_summary %>%
  kbl(caption = "Exponential Model Summary for Each Species at Each Temperature") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = TRUE, fixed_thead = TRUE) %>%
  scroll_box(height = "400px")
Exponential Model Summary for Each Species at Each Temperature
Species Temperature F_Value P_Value Degrees_of_Freedom Equation
value <i>S. lakei</i> 15 69.54162 0 1, 94 log(Growth) = -0.7402 + 0.4132 * Week
value1 <i>S. lakei</i> 20 65.52046 0 1, 94 log(Growth) = -0.7776 + 0.5258 * Week
value2 <i>S. lakei</i> 25 77.08663 0 1, 94 log(Growth) = -0.6257 + 0.5062 * Week
value3 <i>R. evadens</i> 15 158.80206 0 1, 70 log(Growth) = -0.8093 + 0.437 * Week
value4 <i>R. evadens</i> 20 243.68149 0 1, 70 log(Growth) = -0.5387 + 0.4911 * Week
value5 <i>R. evadens</i> 25 496.02153 0 1, 70 log(Growth) = -0.5558 + 0.535 * Week
value6 <i>R. idahoensis</i> 15 1731.68367 0 1, 70 log(Growth) = -0.813 + 0.5467 * Week
value7 <i>R. idahoensis</i> 20 424.62689 0 1, 70 log(Growth) = -0.424 + 0.5793 * Week
value8 <i>R. idahoensis</i> 25 703.79203 0 1, 70 log(Growth) = -0.3219 + 0.6242 * Week
value9 <i>C. geophilum</i> 15 251.03408 0 1, 22 log(Growth) = -0.9864 + 0.4138 * Week
value10 <i>C. geophilum</i> 20 1662.65378 0 1, 22 log(Growth) = -1.0123 + 0.6269 * Week
value11 <i>C. geophilum</i> 25 776.04545 0 1, 22 log(Growth) = -0.9609 + 0.6901 * Week
value12 <i>L. bicolor</i> 15 221.38663 0 1, 22 log(Growth) = -0.2943 + 0.656 * Week
value13 <i>L. bicolor</i> 20 162.61667 0 1, 22 log(Growth) = 0.2903 + 0.5747 * Week
value14 <i>L. bicolor</i> 25 339.84252 0 1, 22 log(Growth) = 0.0793 + 0.5651 * Week

Interactive Exponential Growth Curves for Each Species at Each Temperature

The plot below displays the perfect exponential growth curves for each fungal species at different temperatures. These curves are based on the exponential model fitted to the data, using the equation:

\[ \text{Growth} = e^{(\text{intercept} + \text{slope} \times \text{Week})} \]

Calculation of the Derivative Function for the Exponential Model

For each fungal species at each temperature, an exponential growth model was fitted to the data. The general form of the model is:

\[ \text{Growth} = e^{(\text{intercept} + \text{slope} \times \text{Week})} \]

This model describes how the growth of the fungi changes over time. To determine how fast the growth changes with respect to time (week), we need to compute the derivative of the growth function with respect to the week.

Step 1: Apply the Chain Rule

To compute the derivative of the growth function, we apply the chain rule. The chain rule tells us how to differentiate composite functions like this one, where we have an exponent that depends on another variable (week).

We begin by differentiating the exponential function:

\[ \frac{d}{d\text{Week}} \left( e^{(\text{intercept} + \text{slope} \times \text{Week})} \right) \]

The chain rule gives us two parts: 1. The derivative of the exponential function, which is the same exponential function: \[ e^{(\text{intercept} + \text{slope} \times \text{Week})} \] 2. The derivative of the exponent \((\text{intercept} + \text{slope} \times \text{Week})\) with respect to week. The derivative of this linear term is just the slope: \[ \frac{d}{d\text{Week}} (\text{intercept} + \text{slope} \times \text{Week}) = \text{slope} \]

Step 2: Combine the Results

Multiplying the results of these two derivatives (following the chain rule), we get:

\[ \frac{d(\text{Growth})}{d(\text{Week})} = \text{slope} \times e^{(\text{intercept} + \text{slope} \times \text{Week})} \]

Step 3: Substitution

We know from the original model that:

\[ \text{Growth} = e^{(\text{intercept} + \text{slope} \times \text{Week})} \]

So, we can substitute this back into the derivative equation. Replacing the exponential term with Growth, we arrive at the simplified form:

\[ \frac{d(\text{Growth})}{d(\text{Week})} = \text{Growth} \times \text{slope} \]

What the Derivative Tells Us:

  • The derivative function tells us the rate of growth at any given point in time (week).
  • It shows that the rate of growth is proportional to the current growth value, scaled by the slope of the model.
  • As the fungi grow larger (as Growth increases), their growth rate also increases, but it is controlled by the value of the slope.

In the table below, for each species and temperature combination, the derivative is expressed in the simplified form:

\[ \frac{d(\text{Growth})}{d(\text{Week})} = \text{Growth} \times \text{slope} \]

This equation provides a clear understanding of how the rate of growth evolves over time for each species at each temperature.

# Initialize a data frame to store the simplified derivative functions
derivative_summary <- data.frame(Species = character(), 
                                 Temperature = numeric(), 
                                 Derivative_Function = character(),
                                 stringsAsFactors = FALSE)

# Loop over each species and temperature to compute simplified derivative functions
for(species in unique(df_1_5$Species)) {
  for(temp in unique(df_1_5$Temperature)) {
    
    # Filter the data for this species and temperature
    df_subset <- df_1_5 %>% filter(Species == species, Temperature == temp)
    
    # Fit the exponential model (log-transformed linear)
    exp_model <- lm(log(Growth) ~ Week, data = df_subset)
    
    # Extract the slope of the model
    slope <- coef(exp_model)[2]
    
    # The simplified derivative function is Growth * slope
    derivative_function <- paste0("d(Growth)/d(Week) = Growth * ", round(slope, 4))
    
    # Store the derivative function for this species and temperature
    derivative_summary <- rbind(derivative_summary, 
                                data.frame(Species = species, 
                                           Temperature = temp, 
                                           Derivative_Function = derivative_function))
  }
}

# Display the final table
library(knitr)
library(kableExtra)

# Create a scrollable table
derivative_summary %>%
  kbl(caption = "Simplified Derivative Functions of Exponential Models for Each Species at Each Temperature") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = TRUE, fixed_thead = TRUE) %>%
  scroll_box(height = "400px")
Simplified Derivative Functions of Exponential Models for Each Species at Each Temperature
Species Temperature Derivative_Function
<i>S. lakei</i> 15 d(Growth)/d(Week) = Growth * 0.4132
<i>S. lakei</i> 20 d(Growth)/d(Week) = Growth * 0.5258
<i>S. lakei</i> 25 d(Growth)/d(Week) = Growth * 0.5062
<i>R. evadens</i> 15 d(Growth)/d(Week) = Growth * 0.437
<i>R. evadens</i> 20 d(Growth)/d(Week) = Growth * 0.4911
<i>R. evadens</i> 25 d(Growth)/d(Week) = Growth * 0.535
<i>R. idahoensis</i> 15 d(Growth)/d(Week) = Growth * 0.5467
<i>R. idahoensis</i> 20 d(Growth)/d(Week) = Growth * 0.5793
<i>R. idahoensis</i> 25 d(Growth)/d(Week) = Growth * 0.6242
<i>C. geophilum</i> 15 d(Growth)/d(Week) = Growth * 0.4138
<i>C. geophilum</i> 20 d(Growth)/d(Week) = Growth * 0.6269
<i>C. geophilum</i> 25 d(Growth)/d(Week) = Growth * 0.6901
<i>L. bicolor</i> 15 d(Growth)/d(Week) = Growth * 0.656
<i>L. bicolor</i> 20 d(Growth)/d(Week) = Growth * 0.5747
<i>L. bicolor</i> 25 d(Growth)/d(Week) = Growth * 0.5651

Rate of Growth Curves Based on the Derivative of the Exponential Model

Raw Growth Rate

The raw growth rate was calculated for each fungal strain on each plate, at every temperature and time point (week). This method provides the growth rate for each individual replicate, without aggregating across plates. The growth rate measures how much the fungal colony’s area increased between consecutive time points.

The growth rate was computed using the following formula:

\[ \text{Growth Rate} = \frac{\text{Growth at Week}_n - \text{Growth at Week}_{n-1}}{\text{Week}_n - \text{Week}_{n-1}} \]

###Aggregated Raw Growth Rate for Each Species at Different Temperatures

This figure displays the aggregated raw growth rates for multiple fungal species grown at various temperatures (15°C, 20°C, and 25°C). The growth rate is calculated based on the change in the mean growth between consecutive weeks, aggregated across multiple replicate plates for each species at each temperature.

Generated Niche Curve

This niche curve represents the growth rate at week 5 (The highest growth rate) for various fungal species grown at different temperatures (15°C, 20°C, and 25°C). The growth rate was calculated using the derivative of an exponential growth model fitted to each species’ growth data.

# Step 1: Fit an exponential model for each species and temperature, and calculate the growth rate at Week 5
df_growth_rate_week5 <- data.frame(Species = character(), 
                                   Temperature = numeric(), 
                                   Growth_Rate_Week5 = numeric(), 
                                   stringsAsFactors = FALSE)

for(species in unique(df_1_5$Species)) {
  for(temp in unique(df_1_5$Temperature)) {
    
    # Filter the data for this species and temperature
    df_subset <- df_1_5 %>% filter(Species == species, Temperature == temp)
    
    # Fit the exponential model (log-transformed linear)
    exp_model <- lm(log(Growth) ~ Week, data = df_subset)
    
    # Extract coefficients for the model (intercept and slope)
    intercept <- coef(exp_model)[1]
    slope <- coef(exp_model)[2]
    
    # Calculate the growth at Week 5
    growth_at_week5 <- exp(intercept + slope * 5)  # Growth at week 5
    
    # Calculate the derivative (growth rate) at Week 5
    growth_rate_at_week5 <- growth_at_week5 * slope
    
    # Store the results in the dataframe
    df_growth_rate_week5 <- rbind(df_growth_rate_week5, 
                                  data.frame(Species = species, 
                                             Temperature = as.numeric(temp),  # Ensure Temperature is numeric
                                             Growth_Rate_Week5 = growth_rate_at_week5))
  }
}

# Step 2: Create the plot of maximum growth rate at week 5 for each temperature
plot_growth_rate_temp <- ggplot(df_growth_rate_week5, aes(x = Temperature, y = Growth_Rate_Week5, color = Species)) +
  geom_point(size = 4) +  # Plot points for growth rate at week 5
  geom_line(aes(group = Species), size = 1.2) +  # Connect points by species
  scale_x_continuous(breaks = c(15, 20, 25), labels = c("15°C", "20°C", "25°C")) +  # Label temperature in °C
  labs(title = "Niche Curve of Different Fungi",
       x = "Temperature (°C)", y = "Growth Rate at Week 5 (cm^2 per Week)") +
  theme_minimal() +
  theme(
    strip.text.x = element_text(size = 10),  # Adjust species label size
    axis.text = element_text(size = 10),     # Adjust axis text size
    axis.title = element_text(size = 12),    # Adjust axis title size
    plot.title = element_text(size = 14, face = "bold"),  # Adjust title size
    legend.position = "right"                # Keep the legend for species
  )

# Step 3: Convert to interactive plot using plotly
interactive_plot_growth_rate_temp <- ggplotly(plot_growth_rate_temp)

# Step 4: Display the interactive plot
interactive_plot_growth_rate_temp

Raw Aggregated Niche Curve

# Step 1: Aggregate the data by calculating the mean growth for each species, temperature, and week across plates
df_aggregated <- df_1_5 %>%
  group_by(Species, Temperature, Week) %>%
  summarize(
    Mean_Growth = mean(Growth, na.rm = TRUE)  # Calculate mean growth across plates
  ) %>%
  arrange(Species, Temperature, Week)

# Step 2: Calculate the growth rate using the aggregated data
df_aggregated_growth_rate <- df_aggregated %>%
  mutate(
    Previous_Week = lag(Week),  # Previous week for each species and temperature
    Previous_Mean_Growth = lag(Mean_Growth),  # Previous mean growth value
    Growth_Rate = ifelse(is.na(Previous_Week) | is.na(Previous_Mean_Growth), 0, 
                         (Mean_Growth - Previous_Mean_Growth) / (Week - Previous_Week))  # Calculate mean growth rate
  ) %>%
  ungroup()

# Step 3: Find the maximum growth rate for each species and temperature
df_max_growth_rate <- df_aggregated_growth_rate %>%
  group_by(Species, Temperature) %>%
  summarize(Max_Growth_Rate = max(Growth_Rate, na.rm = TRUE)) %>%
  mutate(Temperature = as.numeric(Temperature)) %>%  # Convert Temperature to numeric
  ungroup()

# Step 4: Create the plot of maximum growth rate for each temperature
plot_max_growth_rate_temp <- ggplot(df_max_growth_rate, aes(x = Temperature, y = Max_Growth_Rate, color = Species)) +
  geom_point(size = 4) +  # Plot points for max growth rate
  geom_line(aes(group = Species), size = 1.2) +  # Connect points by species
  scale_x_continuous(breaks = c(15, 20, 25), labels = c("15°C", "20°C", "25°C")) +  # Label temperature in °C
  labs(title = "Raw Niche Curve",
       x = "Temperature (°C)", y = "Maximum Growth Rate (cm^2 per Week)") +
  theme_minimal() +
  theme(
    axis.text = element_text(size = 10),     # Adjust axis text size
    axis.title = element_text(size = 12),    # Adjust axis title size
    plot.title = element_text(size = 14, face = "bold"),  # Adjust title size
    legend.position = "right"                # Keep the legend for species
  )

# Step 5: Convert to interactive plot using plotly
interactive_plot_max_growth_rate_temp <- ggplotly(plot_max_growth_rate_temp)

# Step 6: Display the interactive plot
interactive_plot_max_growth_rate_temp